home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / X11R4 / cmds / X / ddx / sprite.X11R3 / spriteCursor.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-19  |  35.3 KB  |  1,219 lines

  1. /*-
  2.  * spriteCursor.c --
  3.  *    Functions for maintaining the Sun software cursor...
  4.  *
  5.  * Copyright (c) 1987 by the Regents of the University of California
  6.  *
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] =
  18. "$Header: /mic/X11R3/src/cmds/Xsp/ddx/sprite/RCS/spriteCursor.c,v 1.12 89/11/18 20:57:19 tve Exp $ SPRITE (Berkeley)";
  19. #endif lint
  20. /*
  21.  * A cursor can be in one of 3 states:
  22.  *    IN        It is actually in the frame buffer.
  23.  *    OUT       It is not in the frame buffer and the screen should be
  24.  *              consulted for new screenBits before it is replaced.
  25.  *    XING      It is changing state. Used when calling mfb functions to
  26.  *              play with the cursor. Avoids infinite recursion, you know.
  27.  *    
  28.  * Two references for cursor coordinates are being used in this code. 
  29.  * The outside world (dix code) and most of spriteCursors use the cursor 
  30.  * hot-spot as a reference for the cursor's location. spriteCursor internal 
  31.  * code uses the top-left corner of the cursor glyph as a reference 
  32.  * for painting operations. 
  33.  * 
  34.  */
  35.  
  36. #define NEED_EVENTS            /* For SetCursorPosition */
  37. #include    "spriteddx.h"
  38. #include    <windowstr.h>
  39. #include    <regionstr.h>
  40. #include    <dix.h>
  41. #include    <dixstruct.h>
  42. #include    <opaque.h>
  43. #include    <servermd.h>
  44.  
  45. static CursorPtr  currentCursor = NullCursor;    /* Cursor being displayed */
  46. static BoxRec        currentLimits;        /* Box w/in which the hot spot
  47.                          * must stay. */
  48. /*
  49.  * There are four window functions which bypass the usual GC validation
  50.  * path (PaintWindow{Background,Border}, CopyWindow & ClearToBackground)
  51.  * so we must go out of
  52.  * our way to protect the cursor from them. This is accomplished by
  53.  * intercepting the two screen calls which change the window vectors so
  54.  * we can note when they do and substitute our own function which figures
  55.  * out what's going to be nuked and makes sure the cursor isn't there.
  56.  * The structure for the window is tracked in a somewhat sneaky way:
  57.  * we create a new resource class (not type) and use that to associate
  58.  * the WinPrivRec with the window (using the window's id) in the resource
  59.  * table. This makes it easy to find and has the added benefit of freeing
  60.  * the private data when the window is destroyed.
  61.  */
  62. typedef struct {
  63.     void    (*PaintWindowBackground)();
  64.     void    (*PaintWindowBorder)();
  65.     void    (*CopyWindow)();
  66.     void        (*SaveAreas)();
  67.     RegionPtr   (*RestoreAreas)();
  68. } WinPrivRec, *WinPrivPtr;
  69.  
  70. static int    wPrivClass;        /* Resource class for icky private
  71.                      * window structure (WinPrivRec)
  72.                      * needed to protect the cursor
  73.                      * from background/border paintings */
  74.  
  75. /*-
  76.  *-----------------------------------------------------------------------
  77.  * spriteInitCursor --
  78.  *    Initialize the cursor module...
  79.  *
  80.  * Results:
  81.  *    None.
  82.  *
  83.  * Side Effects:
  84.  *    currentCursor is set to NullCursor.
  85.  *
  86.  *-----------------------------------------------------------------------
  87.  */
  88. void
  89. spriteInitCursor ()
  90. {
  91.     currentCursor = NullCursor;
  92.     wPrivClass = CreateNewResourceClass();
  93. }
  94.  
  95. /*-
  96.  *-----------------------------------------------------------------------
  97.  * spriteStencil --
  98.  *    Return the data for a bitmap made by squishing the source bitmap
  99.  *    data through the mask bitmap data. If invert is TRUE, the source
  100.  *    data are inverted before being squished through.
  101.  *
  102.  * Results:
  103.  *    An array of data suitable for passing to PutImage
  104.  *
  105.  * Side Effects:
  106.  *    None.
  107.  *
  108.  *-----------------------------------------------------------------------
  109.  */
  110. static unsigned char *
  111. spriteStencil (source, mask, w, h, invert)
  112.     register unsigned char *source;      /* Source data */
  113.     register unsigned char *mask;        /* Mask data */
  114.     int              w;            /* Width of both */
  115.     int              h;            /* Height of both */
  116.     Bool          invert;       /* Invert source before squishing */
  117. {
  118.     unsigned char          *result;
  119.     register unsigned char *r;
  120.     register int  nbytes;
  121.  
  122.     nbytes = h * PixmapBytePad (w, 1);
  123.     result = (unsigned char *)Xalloc(nbytes);
  124.  
  125.     for (r = result; nbytes--; source++, r++) {
  126.     *r = (invert ? ~ *source : *source) & (mask ? *mask++ : ~0);
  127.     }
  128.  
  129.     return (result);
  130. }
  131.  
  132. /*-
  133.  *-----------------------------------------------------------------------
  134.  * spriteGetPixel --
  135.  *    Given an rgb value, find an equivalent pixel value for it.
  136.  *
  137.  * Results:
  138.  *    The pixel value.
  139.  *
  140.  * Side Effects:
  141.  *    A colormap entry might be allocated...
  142.  *
  143.  *-----------------------------------------------------------------------
  144.  */
  145. static Pixel
  146. spriteGetPixel (pScreen, r, g, b)
  147.     ScreenPtr      pScreen;  /* Screen to allocate from */
  148.     unsigned short r;        /* Red value to use */
  149.     unsigned short g;        /* Green value to use */
  150.     unsigned short b;        /* Blue value to use */
  151. {
  152.     ColormapPtr cmap;
  153.     Pixel       pix;
  154.  
  155.     cmap = (ColormapPtr) LookupID(pScreen->defColormap, RT_COLORMAP, RC_CORE);
  156.     if (!cmap) {
  157.     FatalError("Can't find default colormap in spriteGetPixel\n");
  158.     }
  159.     if (AllocColor(cmap, &r, &g, &b, &pix, 0)) {
  160.     FatalError("Can't alloc pixel (%d,%d,%d) in spriteGetPixel\n",
  161.            r, g, b);
  162.     }
  163.     return (pix);
  164. }
  165. /*-
  166.  *-----------------------------------------------------------------------
  167.  * spriteRealizeCursor --
  168.  *    Realize a cursor for a specific screen. Eventually it will have
  169.  *    to deal with the allocation of a special pixel from the system
  170.  *    colormap, but for now it's fairly simple. Just have to create
  171.  *    pixmaps.
  172.  *
  173.  * Results:
  174.  *
  175.  * Side Effects:
  176.  *    A CrPrivRec is allocated and filled and stuffed into the Cursor
  177.  *    structure given us.
  178.  *
  179.  *-----------------------------------------------------------------------
  180.  */
  181. Bool
  182. spriteRealizeCursor (pScreen, pCursor)
  183.     ScreenPtr      pScreen;      /* Screen for which the cursor should be */
  184.                 /* realized */
  185.     CursorPtr      pCursor;      /* Cursor to realize */
  186. {
  187.     register CrPrivPtr pPriv;
  188.     int         bufWidth;
  189.     GC         *pGC;        /* GC for initializing the source and
  190.                  * invSource pixmaps... */
  191.     unsigned char *stencil;
  192.     BITS32      status;
  193.  
  194.  
  195.     pGC = GetScratchGC (1, pScreen);
  196.  
  197.     pPriv = (CrPrivPtr) Xalloc(sizeof(CrPrivRec));
  198.     pPriv->state = CR_OUT;
  199.     pCursor->devPriv[pScreen->myNum] = (pointer) pPriv;
  200.  
  201.     bufWidth = 2 * pCursor->width;
  202.  
  203.     pPriv->fg = spriteGetPixel(pScreen, pCursor->foreRed,
  204.                 pCursor->foreGreen,
  205.                 pCursor->foreBlue);
  206.     pPriv->bg = spriteGetPixel(pScreen, pCursor->backRed,
  207.                 pCursor->backGreen,
  208.                 pCursor->backBlue);
  209.  
  210.     /*
  211.      * Create the two pixmaps for the off-screen manipulation of the
  212.      * cursor image. The screenBits pixmap is used to hold the contents of
  213.      * the screen before the cursor is put down and the temp pixmap exists
  214.      * to avoid having to create a pixmap each time the cursor is rop'ed
  215.      * in. Both are made the same depth as the screen, for obvious
  216.      * reasons. 
  217.      */
  218.     pPriv->screenBits =
  219.     (PixmapPtr) (*pScreen->CreatePixmap) (pScreen, bufWidth,
  220.                           2 * pCursor->height,
  221.                           pScreen->rootDepth,
  222.                           ZPixmap);
  223.     pPriv->temp =
  224.     (PixmapPtr) (*pScreen->CreatePixmap) (pScreen, bufWidth,
  225.                           2 * pCursor->height,
  226.                           pScreen->rootDepth,
  227.                           ZPixmap);
  228.  
  229.     /*
  230.      * The source and invSource bitmaps are a bit trickier. The idea is to
  231.      * use the source in a PushPixels operation on the foreground pixel of
  232.      * the cursor and the invSource in a PushPixels on the background
  233.      * pixel of the cursor. The tricky thing is both bitmaps must be
  234.      * created from the source bits after being masked by the mask bits.
  235.      * This must, sadly, be done by hand b/c the ddx interface isn't quite
  236.      * rich enough to push a tile through a bitmap. 
  237.      */
  238.     pPriv->source =
  239.     (PixmapPtr) (*pScreen->CreatePixmap) (pScreen, pCursor->width,
  240.                           pCursor->height, 1,
  241.                           XYBitmap);
  242.     ValidateGC(pPriv->source, pGC);
  243.     stencil = spriteStencil(pCursor->source, pCursor->mask,
  244.              pCursor->width, pCursor->height,
  245.              FALSE);
  246.     (*pGC->PutImage) (pPriv->source, pGC, 1,
  247.               0, 0,
  248.               pCursor->width, pCursor->height,
  249.               0,
  250.               XYPixmap,
  251.               stencil);
  252.     Xfree(stencil);
  253.  
  254.     pPriv->srcGC = spriteCreatePrivGC((DrawablePtr)pScreen->devPrivate,
  255.                       GCForeground, &pPriv->fg, &status);
  256.     ValidateGC((DrawablePtr) pScreen->devPrivate, pPriv->srcGC);
  257.  
  258.     pPriv->invSource =
  259.     (PixmapPtr) (*pScreen->CreatePixmap) (pScreen, pCursor->width,
  260.                           pCursor->height, 1,
  261.                           XYBitmap);
  262.     ValidateGC(pPriv->invSource, pGC);
  263.     stencil = spriteStencil(pCursor->source, pCursor->mask,
  264.              pCursor->width, pCursor->height,
  265.              TRUE);
  266.     (*pGC->PutImage) (pPriv->invSource, pGC, 1,
  267.               0, 0,
  268.               pCursor->width, pCursor->height,
  269.               0,
  270.               XYPixmap,
  271.               stencil);
  272.     Xfree(stencil);
  273.  
  274.     pPriv->invSrcGC = spriteCreatePrivGC((DrawablePtr)pScreen->devPrivate,
  275.                     GCForeground, &pPriv->bg, &status);
  276.     ValidateGC((DrawablePtr) pScreen->devPrivate, pPriv->invSrcGC);
  277.  
  278.     FreeScratchGC (pGC);
  279. }
  280.  
  281. /*-
  282.  *-----------------------------------------------------------------------
  283.  * spriteUnrealizeCursor --
  284.  *    Free up the extra state created by spriteRealizeCursor.
  285.  *
  286.  * Results:
  287.  *    TRUE.
  288.  *
  289.  * Side Effects:
  290.  *    All the pixmaps etc. created by spriteRealizeCursor are destroyed
  291.  *    and the private structure is freed.
  292.  *
  293.  *-----------------------------------------------------------------------
  294.  */
  295. Bool
  296. spriteUnrealizeCursor (pScreen, pCursor)
  297.     ScreenPtr      pScreen;      /* Screen for which to unrealize the cursor */
  298.     CursorPtr      pCursor;      /* Cursor to unrealize */
  299. {
  300.     CrPrivPtr   pPriv;
  301.  
  302.     if (currentCursor == pCursor) {
  303.     spriteRemoveCursor();
  304.     currentCursor = NullCursor;
  305.     }
  306.     pPriv = (CrPrivPtr) pCursor->devPriv[pScreen->myNum];
  307.  
  308.     (*pScreen->DestroyPixmap) (pPriv->source);
  309.     (*pScreen->DestroyPixmap) (pPriv->invSource);
  310.     (*pScreen->DestroyPixmap) (pPriv->screenBits);
  311.     (*pScreen->DestroyPixmap) (pPriv->temp);
  312.     /*
  313.      * XXX: Deallocate pixels 
  314.      */
  315.     FreeScratchGC(pPriv->srcGC);
  316.     FreeScratchGC(pPriv->invSrcGC);
  317.  
  318.     Xfree(pPriv);
  319.  
  320.     return TRUE;
  321. }
  322.  
  323. /*-
  324.  *-----------------------------------------------------------------------
  325.  * spriteSetCursorPosition --
  326.  *    Alter the position of the current cursor. The x and y coordinates
  327.  *    are assumed to be legal for the given screen.
  328.  *
  329.  * Results:
  330.  *    TRUE.
  331.  *
  332.  * Side Effects:
  333.  *    The pScreen, x, and y fields of the current pointer's private data
  334.  *    are altered to reflect the new values. I.e. moving the cursor to
  335.  *    a different screen moves the pointer there as well. Helpful...
  336.  *
  337.  *-----------------------------------------------------------------------
  338.  */
  339. Bool
  340. spriteSetCursorPosition (pScreen, hotX, hotY, genEvent)
  341.     ScreenPtr      pScreen;      /* New screen for the cursor */
  342.     unsigned int  hotX;            /* New absolute X coordinate for the cursor */
  343.     unsigned int  hotY;            /* New absolute Y coordinate for the cursor */
  344.     Bool          genEvent;     /* Generate a motion event */
  345. {
  346.     DevicePtr      pDev;
  347.     PtrPrivPtr      pptrPriv;
  348.  
  349.     if (currentCursor == NullCursor) {
  350.     return FALSE;
  351.     } else {
  352.     pDev = LookupPointerDevice();
  353.     
  354.     pptrPriv = (PtrPrivPtr) pDev->devicePrivate;
  355.  
  356.     if (genEvent) {
  357.         /*
  358.          * If we have to generate a motion event here, we need to
  359.          * flush any current motion events to move the cursor to the
  360.          * right place, etc.
  361.          */
  362.         ProcessInputEvents();
  363.     }
  364.     
  365.     if (pScreen == pptrPriv->pScreen) {
  366.         /*
  367.          * Cursor staying on the same screen, let spriteMoveCursor
  368.          * worry about positioning the beastie
  369.          */
  370.         spriteMoveCursor (pScreen, hotX, hotY);
  371.     } else {
  372.         /*
  373.          * Now nuke the cursor and switch its position to the other
  374.          * screen.
  375.          */
  376.         spriteRemoveCursor();
  377.         pptrPriv->pScreen = pScreen;
  378.     }
  379.     pptrPriv->x = hotX;
  380.     pptrPriv->y = hotY;
  381.  
  382.     if (genEvent) {
  383.         /*
  384.          * Have to generate a motion event for DIX. We use the time of
  385.          * the last event plus 1 millisecond since we can't do anything
  386.          * else useful and I assume there will be more than 1 ms between
  387.          * events...maybe.
  388.          */
  389.         xEvent    motion;
  390.         
  391.         motion.u.keyButtonPointer.rootX = hotX;
  392.         motion.u.keyButtonPointer.rootY = hotY;
  393.         lastEventTimeMS += 1;
  394.         motion.u.keyButtonPointer.time = lastEventTimeMS;
  395.         motion.u.u.type = MotionNotify;
  396.         (* pDev->processInputProc) (&motion, pDev);
  397.     }
  398.     return TRUE;
  399.     }
  400. }
  401.  
  402. /*-
  403.  *-----------------------------------------------------------------------
  404.  * spriteCursorLimits --
  405.  *    Return a box within which the given cursor may move on the given
  406.  *    screen. We assume that the HotBox is actually on the given screen,
  407.  *    since dix knows that size.
  408.  *
  409.  * Results:
  410.  *    A box for the hot spot corner of the cursor.
  411.  *
  412.  * Side Effects:
  413.  *    None.
  414.  *
  415.  *-----------------------------------------------------------------------
  416.  */
  417. void
  418. spriteCursorLimits (pScreen, pCursor, pHotBox, pResultBox)
  419.     ScreenPtr      pScreen;      /* Screen on which limits are desired */
  420.     CursorPtr      pCursor;      /* Cursor whose limits are desired */
  421.     BoxPtr        pHotBox;      /* Limits for pCursor's hot point */
  422.     BoxPtr        pResultBox;    /* RETURN: limits for hot spot */
  423. {
  424.     *pResultBox = *pHotBox;
  425. }
  426.  
  427. /*-
  428.  *-----------------------------------------------------------------------
  429.  * spriteDisplayCursor --
  430.  *    Set the current cursor.
  431.  *
  432.  * Results:
  433.  *    TRUE.
  434.  *
  435.  * Side Effects:
  436.  *    The value of currentCursor is altered. Note that the cursor is
  437.  *    *not* placed in the frame buffer until RestoreCursor is called.
  438.  *    Instead, the cursor is marked as out, which will cause it to
  439.  *    be replaced.
  440.  *
  441.  *-----------------------------------------------------------------------
  442.  */
  443. Bool
  444. spriteDisplayCursor (pScreen, pCursor)
  445.     ScreenPtr      pScreen;      /* Screen on which to display cursor */
  446.     CursorPtr      pCursor;      /* Cursor to display */
  447. {
  448.     if (currentCursor) {
  449.     spriteRemoveCursor();
  450.     }
  451.  
  452.     currentCursor = pCursor;
  453.  
  454.     ((CrPrivPtr)pCursor->devPriv[pScreen->myNum])->state = CR_OUT;
  455.     spriteCursorGone();
  456.  
  457.     return TRUE;
  458. }
  459.  
  460. /*-
  461.  *-----------------------------------------------------------------------
  462.  * spriteRecolorCursor --
  463.  *    Change the color of a cursor.
  464.  *
  465.  * Results:
  466.  *    None.
  467.  *
  468.  * Side Effects:
  469.  *    If the screen is a color one
  470.  *
  471.  *-----------------------------------------------------------------------
  472.  */
  473. void
  474. spriteRecolorCursor (pScreen, pCursor, displayed)
  475.     ScreenPtr      pScreen;      /* Screen for which the cursor is to be */
  476.                 /* recolored */
  477.     CursorPtr      pCursor;      /* Cursor to recolor */
  478.     Bool          displayed;    /* True if pCursor being displayed now */
  479. {
  480.     CrPrivPtr      pPriv;
  481.     /*
  482.      * XXX: will have to alter the colormap entries of the foreground and
  483.      * background pixels. For now, just change the pixels...
  484.      */
  485.  
  486.     if (displayed) {
  487.     spriteRemoveCursor();
  488.     }
  489.  
  490.     pPriv = (CrPrivPtr)pCursor->devPriv[pScreen->myNum];
  491.     pPriv->fg = spriteGetPixel(pScreen,
  492.                 pCursor->foreRed,
  493.                 pCursor->foreGreen,
  494.                 pCursor->foreBlue);
  495.     ChangeGC (pPriv->srcGC, GCForeground, &pPriv->fg);
  496.     ValidateGC (pScreen->devPrivate, pPriv->srcGC);
  497.     
  498.     pPriv->bg = spriteGetPixel (pScreen,
  499.                  pCursor->backRed,
  500.                  pCursor->backGreen,
  501.                  pCursor->backBlue);
  502.     ChangeGC (pPriv->invSrcGC, GCForeground, &pPriv->bg);
  503.     ValidateGC (pScreen->devPrivate, pPriv->invSrcGC);
  504. }
  505.  
  506. /*-
  507.  *-----------------------------------------------------------------------
  508.  * spritePointerNonInterestBox --
  509.  *    Set up things to ignore uninteresting mouse events. Sorry.
  510.  *
  511.  * Results:
  512.  *
  513.  * Side Effects:
  514.  *
  515.  *-----------------------------------------------------------------------
  516.  */
  517. /*ARGSUSED*/
  518. void
  519. spritePointerNonInterestBox (pScreen, pBox)
  520.     ScreenPtr      pScreen;  /* Screen for cursor */
  521.     BoxPtr        pBox;        /* Box inside of which motions are boring */
  522. {
  523. }
  524.  
  525. /*-
  526.  *-----------------------------------------------------------------------
  527.  * spriteConstrainCursor --
  528.  *    Make it so the current pointer doesn't let the cursor's
  529.  *      hot-spot wander out of the specified box.
  530.  *    
  531.  * Results:
  532.  *    None.
  533.  *
  534.  * Side Effects:
  535.  *    currentLimits is overwritten.
  536.  *
  537.  *-----------------------------------------------------------------------
  538.  */
  539. /*ARGSUSED*/
  540. void
  541. spriteConstrainCursor (pScreen, pBox)
  542.     ScreenPtr      pScreen;      /* Screen to which it should be constrained */
  543.     BoxPtr        pBox;            /* Box in which... */
  544. {
  545.     currentLimits = *pBox;
  546. }
  547.  
  548. /*-
  549.  *-----------------------------------------------------------------------
  550.  * spriteRemoveCursor --
  551.  *    Remove the current cursor from the screen, if it hasn't been removed
  552.  *    already.
  553.  *
  554.  * Results:
  555.  *    None.
  556.  *
  557.  * Side Effects:
  558.  *    If the cursor is removed, the state field of the cursor-private
  559.  *    structure is set to CR_OUT. In addition, spriteCursorGone is called.
  560.  *
  561.  *-----------------------------------------------------------------------
  562.  */
  563. void
  564. spriteRemoveCursor ()
  565. {
  566.     CrPrivPtr      pPriv;        /* Private data for this cursor */
  567.     ScreenPtr      pScreen;      /* Screen on which the cursor is */
  568.     PtrPrivPtr      pPtrPriv;    /* XXX: Pointer private data */
  569.     DevicePtr      pDev;
  570.     GC              *pGC;
  571.  
  572.     if (currentCursor == NullCursor) {
  573.     return;
  574.     }
  575.  
  576.     pDev = LookupPointerDevice();
  577.  
  578.     pPtrPriv = (PtrPrivPtr) pDev->devicePrivate;
  579.     pScreen = pPtrPriv->pScreen;
  580.     
  581.     pPriv = (CrPrivPtr)currentCursor->devPriv[pScreen->myNum];
  582.  
  583.     if (pPriv->state == CR_IN) {
  584.     /*
  585.      * XXX: Makes use of the devPrivate field of the screen. This *must*
  586.      * be a pixmap representing the entire screen. How else can I get a
  587.      * pixmap to draw to?
  588.      */
  589.  
  590.     pGC = spriteFbs[pScreen->myNum].pGC;
  591.  
  592.     pPriv->state = CR_XING;
  593.     pGC->stateChanges |= (GCForeground|GCBackground);    
  594.         /* Need to set some bits */
  595.     ValidateGC((DrawablePtr)pScreen->devPrivate, pGC);
  596.     (* pGC->CopyArea) (pPriv->screenBits,
  597.                (PixmapPtr)pScreen->devPrivate,
  598.                pGC,
  599.                0, 0,
  600.                pPriv->screenBits->width,
  601.                pPriv->screenBits->height,
  602.                pPriv->scrX, pPriv->scrY);
  603.     pPriv->state = CR_OUT;
  604.     spriteCursorGone();
  605.     }
  606. }
  607.  
  608. /*-
  609.  *-----------------------------------------------------------------------
  610.  * spritePutCursor --
  611.  *    Place the current cursor in the screen at the given coordinates.
  612.  *    screenBits must already have been filled. If 'direct' is FALSE,
  613.  *    the cursor will be drawn into the temp pixmap after the screenBits
  614.  *    have been copied there. The temp pixmap will then be put onto
  615.  *    the screen. Used for more flicker-free cursor motion...
  616.  *
  617.  * Results:
  618.  *    None.
  619.  *
  620.  * Side Effects:
  621.  *    The state field of the private data is set to CR_IN...
  622.  *
  623.  *-----------------------------------------------------------------------
  624.  */
  625.  
  626. static void
  627. spritePutCursor (pScreen, pPriv, hotX, hotY, direct)
  628.     ScreenPtr          pScreen;        /* Screen on which to put it */
  629.     CrPrivPtr          pPriv;            /* Cursor-private data */
  630.     int                  hotX;
  631.     int                  hotY;
  632.     Bool              direct;            /* TRUE if should put the cursor */
  633.                     /* directly onto the screen, not */
  634.                     /* into pPriv->temp first... */
  635. {
  636.     register PixmapPtr    pPixmap;
  637.     register GC          *pGC;
  638.     int           realW,
  639.             realH;
  640.     int            x = hotX - currentCursor->xhot;
  641.     int         y = hotY - currentCursor->yhot;
  642.     
  643.  
  644.     pGC = spriteFbs[pScreen->myNum].pGC;
  645.  
  646.     if (!direct) {
  647.     pPixmap = pPriv->temp;
  648.     
  649.     /*
  650.      * Duplicate the contents of the screen
  651.      */
  652.     pGC->stateChanges |= (GCForeground|GCBackground);
  653.         /* Need to set some bits */
  654.     ValidateGC(pPixmap, pGC);
  655.     (* pGC->CopyArea) (pPriv->screenBits, pPixmap, pGC,
  656.                0, 0, pPixmap->width, pPixmap->height,
  657.                0, 0);
  658.     
  659.     /*
  660.      * First the foreground pixels...
  661.      * Warning: The srcGC is validated with the screen, so the clip list
  662.      * here will be wrong, but it shouldn't matter since we never go
  663.      * outside the pixmap...
  664.      */
  665.     (* pPriv->srcGC->PushPixels) (pPriv->srcGC, pPriv->source, pPixmap,
  666.                       pPriv->source->width,
  667.                       pPriv->source->height,
  668.                       x - pPriv->scrX, y - pPriv->scrY);
  669.  
  670.     /*
  671.      * Then the background pixels
  672.      */
  673.     (* pPriv->invSrcGC->PushPixels) (pPriv->invSrcGC, pPriv->invSource,
  674.                      pPixmap, pPriv->invSource->width,
  675.                      pPriv->invSource->height,
  676.                      x - pPriv->scrX, y - pPriv->scrY);
  677.  
  678.     /*
  679.      * Now put the whole buffer onto the screen
  680.      */
  681.     pPriv->state = CR_XING;
  682.     realW = min(pPixmap->width, pScreen->width - pPriv->scrX);
  683.     realH = min(pPixmap->height,pScreen->height - pPriv->scrY);
  684.  
  685.     pGC->stateChanges |= (GCForeground|GCBackground);
  686.         /* Need to set some bits */
  687.     ValidateGC((DrawablePtr)pScreen->devPrivate, pGC);
  688.     (* pGC->CopyArea) (pPixmap, (PixmapPtr)pScreen->devPrivate, pGC,
  689.                0, 0, realW, realH, pPriv->scrX, pPriv->scrY);
  690.     
  691.     pPriv->state = CR_IN;
  692.     } else {
  693.     pPixmap = (PixmapPtr) pScreen->devPrivate;
  694.  
  695.     /*
  696.      * PushPixels can't handle negative x and y.  Therefore
  697.      * we'll clip here on our own.
  698.      */
  699.     realW = min(pPriv->source->width,pPixmap->width - x);
  700.     realH = min(pPriv->source->height,pPixmap->height - y);
  701.  
  702.     pPriv->state = CR_XING;
  703.     /*
  704.      * First the foreground pixels...
  705.      */
  706.     (* pPriv->srcGC->PushPixels) (pPriv->srcGC, pPriv->source, pPixmap,
  707.                       realW, realH, x, y);
  708.     
  709.     /*
  710.      * Then the background pixels
  711.      */
  712.     (* pPriv->invSrcGC->PushPixels) (pPriv->invSrcGC, pPriv->invSource,
  713.                      pPixmap, realW, realH, x, y);
  714.  
  715.     pPriv->state = CR_IN;
  716.     }
  717. }
  718.  
  719.  
  720. /*-
  721.  *-----------------------------------------------------------------------
  722.  * spriteCursorLoc --
  723.  *    If the current cursor is both on and in the given screen,
  724.  *    fill in the given BoxRec with the extent of the cursor and return
  725.  *    TRUE. If the cursor is either on a different screen or not
  726.  *    currently in the frame buffer, return FALSE.
  727.  *
  728.  * Results:
  729.  *    TRUE or FALSE, as above.
  730.  *
  731.  * Side Effects:
  732.  *    None.
  733.  *
  734.  *-----------------------------------------------------------------------
  735.  */
  736. Bool
  737. spriteCursorLoc (pScreen, pBox)
  738.     ScreenPtr      pScreen;      /* Affected screen */
  739.     BoxRec      *pBox;    /* Box in which to place the limits */
  740. {
  741.     PtrPrivPtr      pptrPriv;
  742.     CrPrivPtr      pPriv;
  743.     DevicePtr      pDev;
  744.  
  745.     if (currentCursor == NullCursor) {
  746.     /*
  747.      * Firewall: Might be called when initially putting down the cursor
  748.      */
  749.     return FALSE;
  750.     }
  751.  
  752.     pDev = LookupPointerDevice();
  753.     pptrPriv = (PtrPrivPtr) pDev->devicePrivate;
  754.     pPriv = (CrPrivPtr) currentCursor->devPriv[pScreen->myNum];
  755.  
  756.     if ((pptrPriv->pScreen == pScreen) && (pPriv->state == CR_IN)) {
  757.     /*
  758.      * If the cursor is actually on the same screen, stuff the cursor's
  759.      * limits in the given BoxRec. Perhaps this should be done when
  760.      * the cursor is moved? Probably not important...
  761.      */
  762.  
  763.     pBox->x1 = pPriv->scrX;
  764.     pBox->y1 = pPriv->scrY;
  765.     pBox->x2 = pPriv->scrX + pPriv->screenBits->width;
  766.     pBox->y2 = pPriv->scrY + pPriv->screenBits->height;
  767.     return TRUE;
  768.     } else {
  769.     return FALSE;
  770.     }
  771. }
  772.  
  773. /*-
  774.  *-----------------------------------------------------------------------
  775.  * spriteRestoreCursor --
  776.  *    Redraw the cursor if it was removed.
  777.  *
  778.  * Results:
  779.  *    None.
  780.  *
  781.  * Side Effects:
  782.  *    The cursor may be replaced and the 'state' field changed.
  783.  *
  784.  *-----------------------------------------------------------------------
  785.  */
  786. void
  787. spriteRestoreCursor()
  788. {
  789.     PtrPrivPtr          pptrPriv;
  790.     CrPrivPtr          pPriv;
  791.     ScreenPtr          pScreen;
  792.     DevicePtr        pDev;
  793.     GC                  *pGC;
  794.     register PixmapPtr    screenBits;
  795.     int                  scrX, scrY;
  796.  
  797.     pDev = LookupPointerDevice();
  798.  
  799.     pptrPriv = (PtrPrivPtr) pDev->devicePrivate;
  800.     pScreen = pptrPriv->pScreen;
  801.     pPriv = (CrPrivPtr) currentCursor->devPriv[pScreen->myNum];
  802.     screenBits = pPriv->screenBits;
  803.  
  804.     if (pPriv->state == CR_OUT) {
  805.     /*
  806.      * Since the buffer pixmap is four times as large as the cursor and
  807.      * we would always like to center the thing so as to allow the same
  808.      * leeway for movement, in spriteMoveCursor, on each side, we place the
  809.      * top-left corner of the cursor at the intersection of the first
  810.      * quarter lines by shifting the position of the buffer pixmap
  811.      */
  812.     scrX = pptrPriv->x - currentCursor->xhot - screenBits->width / 4;
  813.     scrY = pptrPriv->y - currentCursor->yhot - screenBits->height / 4;
  814.  
  815.     /*
  816.      * In general we're trying to store some of the bits surrounding the
  817.      * cursor.  We try to center the cursor in the area we're
  818.          * saving; that is what the previous two lines are doing.  But if we're
  819.          * at the top left already, we won't try to center the cursor; we'll
  820.      * just save from [0,0].
  821.      */
  822.     if (scrX < 0) {
  823.         scrX = 0;
  824.     }
  825.     if (scrY < 0) {
  826.         scrY = 0;
  827.     }
  828.  
  829.     pPriv->scrX = scrX;
  830.     pPriv->scrY = scrY;
  831.     
  832.     pGC = spriteFbs[pScreen->myNum].pGC;
  833.     pGC->stateChanges |= (GCForeground|GCBackground);    
  834.         /* Need to set some bits */
  835.     ValidateGC(screenBits, pGC);
  836.     (* pGC->CopyArea) ((DrawablePtr)pScreen->devPrivate,
  837.                (DrawablePtr)screenBits,
  838.                pGC,
  839.                scrX, scrY,
  840.                screenBits->width, screenBits->height,
  841.                0, 0);
  842.     spritePutCursor (pScreen, pPriv, pptrPriv->x, pptrPriv->y, TRUE);
  843.     }
  844. }
  845.  
  846. /*-
  847.  *-----------------------------------------------------------------------
  848.  * spriteMoveCursor --
  849.  *    Shift a the current cursor by a given amount. If the change keeps
  850.  *    the cursor within its screenBits pixmap, the whole thing is
  851.  *    simply drawn over the old position. Otherwise, the cursor is
  852.  *    removed and must be redrawn before we sleep. The pointer's
  853.  *    coordinates need not have been updated before this is called.
  854.  *
  855.  * Results:
  856.  *    None.
  857.  *
  858.  * Side Effects:
  859.  *    The cursor may be removed...
  860.  *
  861.  *-----------------------------------------------------------------------
  862.  */
  863. void
  864. spriteMoveCursor (pScreen, hotX, hotY)
  865.     ScreenPtr      pScreen;      /* Screen cursor's currently on */
  866.     int              hotX;          /* Cursor's new X coordinate */
  867.     int              hotY;          /* Cursor's new Y coordinate */
  868. {
  869.     CrPrivPtr      pPriv;
  870.  
  871.     pPriv = (CrPrivPtr) currentCursor->devPriv[pScreen->myNum];
  872.  
  873.     if (pPriv->state == CR_OUT) {
  874.     return;
  875.     }
  876.  
  877.     if ((hotX - currentCursor->xhot >= pPriv->scrX) &&
  878.     ((hotX - currentCursor->xhot + currentCursor->width) <
  879.      (pPriv->scrX + pPriv->screenBits->width))&&
  880.     (hotY - currentCursor->yhot >= pPriv->scrY) &&
  881.     ((hotY - currentCursor->yhot + currentCursor->height) <
  882.      (pPriv->scrY + pPriv->screenBits->height))) {
  883.          /*
  884.           * If the entire cursor at its new position remains inside the
  885.           * box buffered in the screenBits pixmap, then its ok to just
  886.           * place the cursor inside the box and draw the entire box
  887.           * onto the screen. The hope is that this redrawing, rather than
  888.           * removing the cursor and redrawing it, will cause it to flicker
  889.           * less than it did in V10...
  890.           */
  891.          spritePutCursor (pScreen, pPriv, hotX, hotY, FALSE);
  892.     } else {
  893.     /*
  894.      * The cursor is no longer within the screenBits pixmap, so we just
  895.      * remove it. dix will RestoreCursor() it back onto the screen.
  896.      */
  897.     spriteRemoveCursor();
  898.     }
  899. }
  900.  
  901. /*-
  902.  *-----------------------------------------------------------------------
  903.  * spriteConstrainXY --
  904.  *    Given an X and Y coordinate, alter them to fit within the current
  905.  *    cursor constraints.  Used by mouse processing code to adjust 
  906.  *     position reported by hardware.
  907.  *    
  908.  *
  909.  * Results:
  910.  *    The new constrained coordinates. Returns FALSE if the motion
  911.  *    event should be discarded...
  912.  *
  913.  * Side Effects:
  914.  *    guess what?
  915.  *
  916.  *-----------------------------------------------------------------------
  917.  */
  918. Bool
  919. spriteConstrainXY (px, py)
  920.     short      *px;
  921.     short           *py;    
  922. {
  923.     *px = max(currentLimits.x1,min(currentLimits.x2,*px));
  924.     *py = max(currentLimits.y1,min(currentLimits.y2,*py));
  925.     return TRUE;
  926. }
  927.  
  928. /*-
  929.  *-----------------------------------------------------------------------
  930.  * spritePaintWindow --
  931.  *    Paint either the window's border or background while preserving
  932.  *    the cursor.
  933.  *
  934.  * Results:
  935.  *    None.
  936.  *
  937.  * Side Effects:
  938.  *    The cursor will be removed if it is in the way.
  939.  *
  940.  *-----------------------------------------------------------------------
  941.  */
  942. void
  943. spritePaintWindow (pWin, pRegion, what)
  944.     WindowPtr    pWin;            /* Window to paint */
  945.     RegionPtr    pRegion;        /* Uncovered region in which the painting
  946.                  * should be done */
  947.     int        what;            /* PW_BACKGROUND to paint the background
  948.                  * PW_BORDER to paint the border */
  949. {
  950.     BoxRec    cursorBox;      /* Current cursor area */
  951.     WinPrivPtr    pPriv;            /* Private data for the window */
  952.     ScreenPtr    pScreen;        /* The screen the window is on */
  953.  
  954.     pScreen = pWin->drawable.pScreen;
  955.  
  956.     if (spriteCursorLoc (pScreen, &cursorBox)) {
  957.     /*
  958.      * If the cursor is on the same screen as the window, check the
  959.      * region to paint for the cursor and remove it as necessary
  960.      */
  961.     if ((* pScreen->RectIn) (pRegion, &cursorBox) != rgnOUT) {
  962.         spriteRemoveCursor();
  963.     }
  964.     }
  965.  
  966.     pPriv = (WinPrivPtr) LookupID (pWin->wid, RT_WINDOW, wPrivClass);
  967.     if (what == PW_BACKGROUND) {
  968.     (* pPriv->PaintWindowBackground) (pWin, pRegion, what);
  969.     } else {
  970.     (* pPriv->PaintWindowBorder) (pWin, pRegion, what);
  971.     }
  972. }
  973.  
  974. /*-
  975.  *-----------------------------------------------------------------------
  976.  * spriteCopyWindow --
  977.  *    Protect the cursor from window copies..
  978.  *
  979.  * Results:
  980.  *    None.
  981.  *
  982.  * Side Effects:
  983.  *    The cursor may be removed.
  984.  *
  985.  *-----------------------------------------------------------------------
  986.  */
  987. void
  988. spriteCopyWindow (pWin, ptOldOrg, prgnSrc)
  989.     WindowPtr      pWin;        /* Window being copied */
  990.     DDXPointRec      ptOldOrg; /* Old absolute origin for window */
  991.     RegionPtr      prgnSrc;  /* Region from which window is being copied. */
  992. {
  993.     BoxRec    cursorBox;
  994.     WinPrivPtr    pPriv;
  995.     ScreenPtr    pScreen;
  996.  
  997.     pScreen = pWin->drawable.pScreen;
  998.  
  999.     if (spriteCursorLoc (pScreen, &cursorBox)) {
  1000.     /*
  1001.      * If the cursor is on the same screen, compare the box for the
  1002.      * cursor against the original window clip region (prgnSrc) and
  1003.      * the current window clip region (pWin->borderClip) and if it
  1004.      * overlaps either one, remove the cursor. (Should it really be
  1005.      * borderClip?)
  1006.      */
  1007.     switch ((* pScreen->RectIn) (prgnSrc, &cursorBox)) {
  1008.         case rgnOUT:
  1009.         if ((* pScreen->RectIn) (pWin->borderClip, &cursorBox) ==
  1010.             rgnOUT) {
  1011.             break;
  1012.         }
  1013.         case rgnIN:
  1014.         case rgnPART:
  1015.         spriteRemoveCursor();
  1016.     }
  1017.     }
  1018.  
  1019.     pPriv = (WinPrivPtr) LookupID (pWin->wid, RT_WINDOW, wPrivClass);
  1020.     (* pPriv->CopyWindow) (pWin, ptOldOrg, prgnSrc);
  1021. }
  1022.  
  1023. /*-
  1024.  *-----------------------------------------------------------------------
  1025.  * spriteSaveAreas --
  1026.  *    Keep the cursor from getting in the way of any SaveAreas operation
  1027.  *    by backing-store.
  1028.  *
  1029.  * Results:
  1030.  *    None.
  1031.  *
  1032.  * Side Effects:
  1033.  *    The cursor may be removed.
  1034.  *
  1035.  *-----------------------------------------------------------------------
  1036.  */
  1037. void
  1038. spriteSaveAreas(pWin)
  1039.     WindowPtr      pWin;
  1040. {
  1041.     BoxRec        cursorBox;
  1042.     WinPrivPtr      pPriv;
  1043.     ScreenPtr      pScreen;
  1044.  
  1045.     pScreen = pWin->drawable.pScreen;
  1046.  
  1047.     if (spriteCursorLoc(pScreen, &cursorBox)) {
  1048.     /*
  1049.      * If the areas are obscured because the window moved, we need to
  1050.      * translate the box to the correct relationship with the region,
  1051.      * which is at the new window coordinates.
  1052.      */
  1053.     int dx, dy;
  1054.  
  1055.     dx = pWin->absCorner.x - pWin->backStorage->oldAbsCorner.x;
  1056.     dy = pWin->absCorner.y - pWin->backStorage->oldAbsCorner.y;
  1057.  
  1058.     if (dx || dy) {
  1059.         cursorBox.x1 += dx;
  1060.         cursorBox.y1 += dy;
  1061.         cursorBox.x2 += dx;
  1062.         cursorBox.y2 += dy;
  1063.     }
  1064.     if ((* pScreen->RectIn) (pWin->backStorage->obscured, &cursorBox) != rgnOUT) {
  1065.         spriteRemoveCursor();
  1066.     }
  1067.     }
  1068.     pPriv = (WinPrivPtr) LookupID (pWin->wid, RT_WINDOW, wPrivClass);
  1069.     (* pPriv->SaveAreas) (pWin);
  1070. }
  1071.  
  1072. /*-
  1073.  *-----------------------------------------------------------------------
  1074.  * spriteRestoreAreas --
  1075.  *    Keep the cursor from getting in the way of any RestoreAreas operation
  1076.  *    by backing-store.
  1077.  *
  1078.  * Results:
  1079.  *    None.
  1080.  *
  1081.  * Side Effects:
  1082.  *    The cursor may be removed.
  1083.  *
  1084.  *-----------------------------------------------------------------------
  1085.  */
  1086. RegionPtr
  1087. spriteRestoreAreas(pWin)
  1088.     WindowPtr      pWin;
  1089. {
  1090.     BoxRec        cursorBox;
  1091.     WinPrivPtr      pPriv;
  1092.     ScreenPtr      pScreen;
  1093.  
  1094.     pScreen = pWin->drawable.pScreen;
  1095.  
  1096.     if (spriteCursorLoc(pScreen, &cursorBox)) {
  1097.     /*
  1098.      * The exposed region is now window-relative, so we have to make the
  1099.      * cursor box window-relative too.
  1100.      */
  1101.     cursorBox.x1 -= pWin->absCorner.x;
  1102.     cursorBox.x2 -= pWin->absCorner.x;
  1103.     cursorBox.y1 -= pWin->absCorner.y;
  1104.     cursorBox.y2 -= pWin->absCorner.y;
  1105.     if ((* pScreen->RectIn) (pWin->exposed, &cursorBox) != rgnOUT) {
  1106.         spriteRemoveCursor();
  1107.     }
  1108.     }
  1109.     pPriv = (WinPrivPtr) LookupID (pWin->wid, RT_WINDOW, wPrivClass);
  1110.     return (* pPriv->RestoreAreas) (pWin);
  1111. }
  1112.  
  1113. /*-
  1114.  *-----------------------------------------------------------------------
  1115.  * spriteCreateWindow --
  1116.  *    A way to get our hooks into a new window to keep the cursor from
  1117.  *    being obliterated. We first allow the output library for the
  1118.  *    screen to install its vectors and then stuff our own in their
  1119.  *    places.
  1120.  *
  1121.  * Results:
  1122.  *    TRUE.
  1123.  *
  1124.  * Side Effects:
  1125.  *    A WinPrivRec is allocated and stored under the window's ID.
  1126.  *    The PaintWindowBackground and PaintWindowBorder and CopyWindow
  1127.  *    vectors for the new window are overwritten.
  1128.  *
  1129.  *-----------------------------------------------------------------------
  1130.  */
  1131. Bool
  1132. spriteCreateWindow (pWin)
  1133.     WindowPtr    pWin;
  1134. {
  1135.     WinPrivPtr    pPriv;
  1136.  
  1137.     (* spriteFbs[((DrawablePtr)pWin)->pScreen->myNum].CreateWindow) (pWin);
  1138.  
  1139.     pPriv = (WinPrivPtr) Xalloc (sizeof (WinPrivRec));
  1140.     pPriv->PaintWindowBackground =  pWin->PaintWindowBackground;
  1141.     pPriv->PaintWindowBorder =         pWin->PaintWindowBorder;
  1142.     pPriv->CopyWindow =             pWin->CopyWindow;
  1143.  
  1144.     pWin->PaintWindowBackground =   spritePaintWindow;
  1145.     pWin->PaintWindowBorder =         spritePaintWindow;
  1146.     pWin->CopyWindow =                spriteCopyWindow;
  1147.  
  1148.     if (pWin->backStorage) {
  1149.     pPriv->SaveAreas = pWin->backStorage->SaveDoomedAreas;
  1150.     pWin->backStorage->SaveDoomedAreas = spriteSaveAreas;
  1151.     pPriv->RestoreAreas = pWin->backStorage->RestoreAreas;
  1152.     pWin->backStorage->RestoreAreas = spriteRestoreAreas;
  1153.     }
  1154.     AddResource (pWin->wid, RT_WINDOW, (pointer)pPriv, Xfree, wPrivClass);
  1155. }
  1156.  
  1157. /*-
  1158.  *-----------------------------------------------------------------------
  1159.  * spriteChangeWindowAttributes --
  1160.  *    Catch the changing of the background/border functions when a
  1161.  *    window is reconfigured.
  1162.  *
  1163.  * Results:
  1164.  *    TRUE.
  1165.  *
  1166.  * Side Effects:
  1167.  *    The three vectors we intercept will be restored to the rightful
  1168.  *    value if they have been changed.
  1169.  *
  1170.  *-----------------------------------------------------------------------
  1171.  */
  1172. Bool
  1173. spriteChangeWindowAttributes (pWin, mask)
  1174.     WindowPtr    pWin;        /* Window being altered */
  1175.     Mask    mask;        /* Mask of changes to the window */
  1176. {
  1177.     WinPrivPtr    pPriv;
  1178.  
  1179.     (* spriteFbs[((DrawablePtr)pWin)->pScreen->myNum].ChangeWindowAttributes)
  1180.     (pWin, mask);
  1181.     
  1182.     pPriv = (WinPrivPtr) LookupID (pWin->wid, RT_WINDOW, wPrivClass);
  1183.  
  1184.     if (pPriv == (WinPrivPtr)0) {
  1185.     FatalError ("spriteChangeWindowAttributes got null private data");
  1186.     }
  1187.  
  1188.     if ((void (*)())pWin->PaintWindowBackground !=
  1189.     (void (*)())spritePaintWindow){
  1190.         pPriv->PaintWindowBackground = pWin->PaintWindowBackground;
  1191.         pWin->PaintWindowBackground = spritePaintWindow;
  1192.     }
  1193.  
  1194.     if ((void (*)())pWin->PaintWindowBorder !=
  1195.     (void (*)())spritePaintWindow) {
  1196.         pPriv->PaintWindowBorder = pWin->PaintWindowBorder;
  1197.         pWin->PaintWindowBorder = spritePaintWindow;
  1198.     }
  1199.  
  1200.     if ((void (*)())pWin->CopyWindow != (void (*)())spriteCopyWindow) {
  1201.     pPriv->CopyWindow = pWin->CopyWindow;
  1202.     pWin->CopyWindow = spriteCopyWindow;
  1203.     }
  1204.  
  1205.     if (pWin->backStorage &&
  1206.     ((void (*)())pWin->backStorage->SaveDoomedAreas != (void (*)())spriteSaveAreas)){
  1207.         pPriv->SaveAreas = pWin->backStorage->SaveDoomedAreas;
  1208.         pWin->backStorage->SaveDoomedAreas = spriteSaveAreas;
  1209.     }
  1210.     if (pWin->backStorage &&
  1211.     ((void (*)())pWin->backStorage->RestoreAreas != (void (*)())spriteRestoreAreas)){
  1212.         pPriv->RestoreAreas = pWin->backStorage->RestoreAreas;
  1213.         pWin->backStorage->RestoreAreas = spriteRestoreAreas;
  1214.     }
  1215.  
  1216.     return (TRUE);
  1217. }
  1218.  
  1219.